import { isNotEmpty, clearUserStorage } from '../commons/utils';
import storage from '../commons/storage';
import store from '../store';
import { getApi, getHeader, successHandler, failHandler, startShowLoading } from './config';

/** 缓存请求 */
const pendingRequests = [];

/**
 * 执行缓存请求
 */
const pendingRequestsHandler = () => {
    pendingRequests.forEach(item => {
        item.resolve();
    });
    pendingRequests.length = 0;
};

/**
 * 执行器
 * @returns
 */
const handler = run => {
    return new Promise((resolve, reject) => {
        run(resolve, reject)();
    });
};

/**
 * 刷新登陆态
 * 1. 如果token存在且未过期则直接放行
 * 2. 如果token不存在或者过期了就重新登录
 * 3. 重新登录失败或者是新用户则跳转到注册页面
 * @param {*} callback
 */
const checkToken = run => {
    const token = storage.get('token');
    const expireTime = storage.get('expireTime');
    if (isNotEmpty(token) && isNotEmpty(expireTime) && expireTime * 1000 - Date.now() > 0) {
        return handler(run);
    } else {
        const externalControl = {
            resolve: null
        };
        const interceptPromise = new Promise((resolve, reject) => {
            externalControl.resolve = run(resolve, reject);
        });
        pendingRequests.push(externalControl);
        uni.login({
            success: res => {
                const loginCode = res.code;
                request('loginServ', {
                    loginCode,
                    grantType: 2,
                    // 游客登陆标识
                    userCode: storage.get('userCode') || ''
                })
                    .then(ret => {
                        const { token, expireTime, userId, openKid } = ret.data;
                        storage.set('token', token);
                        storage.set('expireTime', expireTime);
                        storage.set('openKid', openKid);
                        storage.set('userId', userId);
                        pendingRequestsHandler();
                    })
                    .catch(() => {
                        clearUserStorage();
                        const useRoute = store.useRouteStore();
                        if (!useRoute.lockStatus) {
                            uni.navigateTo({
                                url: '/pages-user/login/index'
                            });
                            useRoute.lockStatus = true;
                        }
                        return new Promise(() => {});
                    });
            }
        });
        return interceptPromise;
    }
};

/**
 * http请求函数
 * @param {请求名称} name
 * @param {接口入参} data
 * @description
 *  pem: Boolean 是否由系统拦截处理错误，默认为false
 *  sld: Boolean 是否显示请求loading，默认为true
 *  lmt: Number  如何处理429响应，0 系统拦截(默认)；1 页面自行处理；-1 无任何处理；2 跳转到空态页面; 通常用于处理服务端限流场景
 */
const request = (name = '', data = {}) => {
    const { url, method = 'post', pem = false, sld = true, lmt = 0, timeout = 5000, requireAuth = true } = getApi(name);
    const header = getHeader(name);
    const req = {
        url,
        method,
        header,
        pem,
        sld,
        lmt,
        timeout,
        requireAuth
    };

    /**
     * 请求函数
     * @param {*} resolve
     * @param {*} reject
     * @returns
     */
    const run = (resolve, reject) => {
        return () => {
            startShowLoading(sld);
            uni.request({
                url,
                header,
                method,
                data,
                timeout,
                success(res) {
                    successHandler(req, res, resolve, reject);
                },
                fail: err => {
                    reject('other');
                    failHandler(err);
                }
            });
        };
    };
    if (!requireAuth) {
        return handler(run);
    } else {
        return checkToken(run);
    }
};

export default request;
